#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include "../Sock/Socket.hpp"
#include "../Sock/errno.hpp"
#include "../Sock/Logmessage.hpp"
#include <functional>
#include <pthread.h>
namespace onlineServer
{
    using namespace std;
    
    class Server;
    struct threadData
    {
        threadData(Server* self,int sockfd,std::string clientip="",uint16_t clientport=0)
            :self_(self),sockfd_(sockfd),clientip_(clientip),clientport_(clientport)
        {}

        Server* self_;
        int sockfd_;

        std::string clientip_;
        uint16_t clientport_;
    };

    static const uint16_t gport=8080;
    using func_t=function<void(int,std::string,uint16_t,std::string)>;
    class Server
    {
        uint16_t  port_;
        int listen_fd_;
        func_t callback_;
    public:
        Server(func_t callback,const uint16_t port=gport)
            :listen_fd_(-1),port_(port),callback_(callback)
        {}    
        void init()
        {
           
            listen_fd_=Socket::CreateSock();
            Socket::Setsockopt(listen_fd_);
            Socket::Bind(listen_fd_,port_);
            Socket::Listen(listen_fd_);
        }

        void run()
        {
            for(;;)
            {
                std::string clientip;
                uint16_t clientport=0;
                int sock=Socket::Accept(listen_fd_,&clientip,&clientport);
                cout<<clientip<<"["<<clientport<<"]"<<endl;
                if(sock<0)
                {
                    logMessage(WARNING,"accept err...");
                    continue;
                }
                logMessage(NORMAL,"accept sock [%d] success...",sock);

                //多线程处理
                pthread_t tid;
                threadData* td=new threadData(this,sock,clientip,clientport);
                pthread_create(&tid,nullptr,threadRoutinue,td);               
            }

        }
        ~Server(){}

    private:
        static void* threadRoutinue(void* args)
        {
            pthread_detach(pthread_self());
            threadData* td=static_cast<threadData*>(args);
            td->self_->serverIO(td->sockfd_,td->clientip_,td->clientport_);
            close(td->sockfd_);
            delete td;
            return nullptr;
        }
    public:
        void serverIO(int sock,std::string clientip,uint16_t clientport)
        {
            char  buffer[1024];
            while (true)
            {
                ssize_t n=recv(sock,buffer,sizeof(buffer)-1,0);
                if(n>0)
                {
                    buffer[n]=0;
                    string outbuffer=buffer;
                    cout<<clientip<<"["<<clientport<<"]"<<outbuffer<<endl;
                    callback_(sock,clientip,clientport,outbuffer);//回调
                }
                else if(n==0)
                {
                    logMessage(NORMAL,"client quit and I also quit");
                    break;
                }
            }
        }
        
    };
}